package com.motong.gongdan.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.util.IoUtils;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.motong.gongdan.config.ResponseData;
import com.motong.gongdan.entity.*;
import com.motong.gongdan.enums.ObjectType;
import com.motong.gongdan.mapper.WorkOrderMapper;
import com.motong.gongdan.util.*;
import com.motong.gongdan.vo.H5Vo.Dashboard.vo.ProcessStatisticsVo;
import com.motong.gongdan.vo.H5Vo.common.GroupCountVo;
import com.motong.gongdan.vo.H5Vo.customfield.RadioOptionVo;
import com.motong.gongdan.vo.H5Vo.workOrder.vo.WorkListMergedConditionVo;
import com.motong.gongdan.vo.resp.*;
import com.motong.gongdan.vo.system.CustomField.ColumnsConfigure;
import com.motong.gongdan.vo.system.CustomField.ColumnsConfigureList;
import com.motong.gongdan.vo.system.Erp.vo.PushOrderNumVo;
import com.motong.gongdan.vo.system.dataController.query.WorkOrderOverviewQuery;
import com.motong.gongdan.vo.system.otherVo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author:fff
 * @time:2022/2/25
 */
@Service
@Slf4j
public class WorkOrderService extends ServiceImpl<WorkOrderMapper, WorkOrder> {
    @Value("${qRFilePrefix}")
    private String qRFilePrefix;
    @Resource
    WorkOrderService workOrderService;
    @Resource
    MissionService missionService;
    @Resource
    ProcessesService processesService;
    @Resource
    ProductService productService;
    @Resource
    HandleLogService handleLogService;
    @Resource
    WorkReportService workReportService;
    @Resource
    CustomEventService customEventService;
    @Resource
    CustomNumberService customNumberService;
    @Resource
    UserService userService;
    @Resource
    CustomFieldService customFieldService;
    @Resource
    MongoTemplate mongoTemplate;
    @Resource
    private FormTableDetailService formTableDetailService;
    @Resource
    private ScreenPlanService screenPlanService;
    @Resource
    private FormTableService formTableService;
    @Resource
    private ErpServiceImpl erpService;

    public IPage wipData(WipVo vo) {
        IPage<WipResp> data = workOrderService.getBaseMapper().getArticlesBeingProcessedData(new Page<WipResp>(vo.getPage(), vo.getLimit()),
                new QueryWrapper<WipResp>()
                        .like(StringUtil.isNotBlank(vo.getWorkOrderCode()), "wo.code", vo.getWorkOrderCode())
                        .like(StringUtil.isNotBlank(vo.getProductCode()), "p.code", vo.getProductCode())
                        .like(StringUtil.isNotBlank(vo.getProductName()), "p.name", vo.getProductName())
                        .like(StringUtil.isNotBlank(vo.getProductSpecification()), "p.specification", vo.getProductSpecification())
                        .between(vo.getStartTimeStart() != null && vo.getStartTimeEnd() != null,
                                "wo.start_time", vo.getStartTimeStart(), vo.getStartTimeEnd())
                        .between(vo.getEndTimeStart() != null && vo.getEndTimeEnd() != null,
                                "wo.end_time", vo.getEndTimeStart(), vo.getEndTimeEnd())
                        .in(!CollectionUtils.isEmpty(vo.getWorkOrderState()), "wo.state", vo.getWorkOrderState()));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                WorkOrder wo = workOrderService.getById(d.getId());
                if (StringUtil.isNotBlank(wo.getProcessId())) {
                    List<String> processList = Arrays.asList(wo.getProcessId().split(","));
                    List<ProcessNumberResp> processNumberResp = missionService.getBaseMapper()
                            .getProcessNumberData(new QueryWrapper<ProcessNumberResp>()
                                    .eq("m.work_order_code", d.getWorkOrderCode()).in("p.id", processList));
                    d.setList(processNumberResp);
                }
            });
        }
        return data;
    }

    public ResponseData<?> workOrderEdit(WorkOrderHandleVo vo, HandleLog hl, Integer userId) {
        WorkOrder wo = workOrderService.getById(vo.getId());
        if (Objects.nonNull(vo.getState()) && vo.getState() == 2 && (wo.getState() != 0 && wo.getState() != 1) && wo.getState() != 2) {
            return ResponseData.fail(500, "工单状态非未开始、执行中，不可结束");
        }
        Product product = productService.getById(wo.getProductId());
        Product voProduct = productService.getById(vo.getProductId());
        wo.setEditId(userId);
        // 任务相关信息
        List<Mission> missions = missionService.list(new QueryWrapper<Mission>().eq("work_order_code", wo.getCode()));
        hl.setHandleType("编辑工单").setHandleCode(wo.getCode());
        if (StringUtil.isNotBlank(vo.getCode()) && !vo.getCode().equals(wo.getCode())) {
            // 同步修改任务的工单编号和修改销售订单详情中工单编码
            hl.setId(null);
            missions.forEach(i -> i.setWorkOrderCode(vo.getCode()));
            formTableDetailService.update(new LambdaUpdateWrapper<FormTableDetail>().eq(FormTableDetail::getWorkOrderCode, wo.getCode()).set(FormTableDetail::getWorkOrderCode, vo.getCode()));
            hl.setHandleDetail(String.format("编辑工单成功，【%s】【工单编号】修改为【%s】 ", wo.getCode(), vo.getCode()));
            handleLogService.save(hl);
        }
        if (vo.getProductId() != null && !vo.getProductId().equals(wo.getProductId())) {
            hl.setId(null);
            hl.setHandleDetail(String.format("编辑工单成功，【%s】【产品名称】修改为【%s】", product.getName(), voProduct.getName()));
            handleLogService.save(hl);
            Product p = productService.getById(vo.getProductId());
            missions.forEach(m -> m.setProductCode(p.getCode()));
        }
        if (StringUtil.isNotBlank(vo.getComment()) && !vo.getComment().equals(wo.getComment())) {
            hl.setId(null);
            hl.setHandleDetail(String.format("编辑工单成功，【%s】【备注】修改为【%s】", wo.getComment(), vo.getComment()));
            handleLogService.save(hl);
        }
        if (vo.getPlanedNumber() != null && vo.getPlanedNumber().compareTo(wo.getPlanedNumber()) != 0) {
            hl.setId(null);
            // 修改任务的计划数量
            formTableDetailService.update(new LambdaUpdateWrapper<FormTableDetail>().eq(FormTableDetail::getWorkOrderCode, wo.getCode()).set(FormTableDetail::getHandleNumber, vo.getPlanedNumber()));
            hl.setHandleDetail(String.format("编辑工单成功，【%s】【计划数】修改为【%s】", wo.getPlanedNumber(), vo.getPlanedNumber()));
            handleLogService.save(hl);
        }
        if (vo.getStartTime() != null && vo.getEndTime() != null && (!vo.getStartTime().equals(wo.getStartTime()) || !vo.getEndTime().equals(wo.getEndTime()))) {
            hl.setId(null);
            hl.setHandleDetail(String.format("编辑工单成功，【%s-%s】【计划时间】修改为【%s-%s】", wo.getStartTime(), wo.getEndTime(), vo.getStartTime(), vo.getEndTime()));
            handleLogService.save(hl);
        }

        // 0 不变, 1 转结束, 2 撤回
        Integer sysFlag = 0;

        if (Objects.nonNull(vo.getState())) {
            // 任务状态修改
            if ((wo.getState() == 2 && vo.getState() == 1) || (vo.getState() == 2 || vo.getState() == 0)) {
                missions.forEach(m -> {
                    if (wo.getState() == 2 && vo.getState() == 1) {
                        //根据计划数和良品数判断任务状态
                        m.setProcessState(m.getGoodProductNumber().compareTo(BigDecimal.ZERO));
                        m.setProcessState(m.getPlanedNumber().compareTo(m.getGoodProductNumber()) <= 0 ? 2 : m.getProcessState());
                    } else {
                        // 修改为已结束或者未开始状态时
                        m.setProcessState(vo.getState());
                    }
                });
            }
            // 工单实际时间处理
            switch (vo.getState()) {
                case 0:
                    hl.setId(null);
                    wo.setActualStartTime(null);
                    wo.setActualEndTime(null);
                    hl.setHandleDetail("编辑工单成功，【工单状态】修改为未开始");
                    handleLogService.save(hl);
                    break;
                case 1:
                    hl.setId(null);
                    wo.setActualEndTime(null);
                    wo.setActualStartTime(new Date());
                    hl.setHandleDetail("编辑工单成功，【工单状态】修改为执行中");
                    handleLogService.save(hl);
                    break;
                case 2:
                    hl.setId(null);
                    wo.setActualEndTime(new Date());
                    hl.setHandleDetail("编辑工单成功，【工单状态】修改为已结束");
                    handleLogService.save(hl);
                    break;
            }
            if (vo.getState().equals(2) && vo.getState() > wo.getState()) {
                sysFlag = 1;
            }
            if (wo.getState().equals(2) && vo.getState() < 2) {
                sysFlag = 2;
            }
            wo.setState(vo.getState());
        }
        missionService.updateBatchById(missions);
        SpringUtil.copyPropertiesIgnoreNull(vo, wo);
        if (StringUtils.hasLength(vo.getDelMissionId())) {
            List<String> delMissionList = Arrays.asList(vo.getDelMissionId().split(","));
            Set<String> delMissionSet = new HashSet<>(delMissionList);
            if (StringUtils.hasLength(vo.getProcessIds())) {
                wo.setProcessId(vo.getProcessIds());
            } else {
                String existIds = Arrays.stream(wo.getProcessId().split(",")).filter(delMissionSet::add).collect(Collectors.joining(","));
                wo.setProcessId(existIds);
            }

            missionService.removeByIds(delMissionList);
            workReportService.remove(new LambdaQueryWrapper<WorkReport>().in(WorkReport::getMissionId, delMissionList));
        }
        if (!CollectionUtils.isEmpty(vo.getProcess())) {
            for (MissionProcessVo v : vo.getProcess()) {
                Processes pro = processesService.getById(v.getId());
                Mission mission = missionService.getById(v.getMissionId());
                if (mission != null) {
                    mission.setPlanedNumber(v.getPlanedNumber());
                    mission.setStartTime(v.getStartTime());
                    mission.setEndTime(v.getEndTime());
                    mission.setLast(v.getOrder());
                    //判断 良品数是否大于 计划数
                    if (mission.getPlanedNumber().compareTo(mission.getGoodProductNumber()) > 0 && mission.getGoodProductNumber().compareTo(BigDecimal.ZERO) != 0) { //大于
                        mission.setProcessState(1);
                    }
                    if (mission.getGoodProductNumber().compareTo(BigDecimal.ZERO) == 0) {
                        mission.setProcessState(0);
                    }
                    if (mission.getPlanedNumber().compareTo(mission.getGoodProductNumber()) <= 0) {
                        mission.setProcessState(2);
                    }
                    if (v.getRate() != null) {
                        BigDecimal rate = mission.getPlanedNumber().divide(wo.getPlanedNumber(), 6, RoundingMode.DOWN);
                        mission.setRate(rate);
                    }
                    // 添加工序自定义字段
                    if (Objects.nonNull(v.getCustomFieldVos()) && !v.getCustomFieldVos().isEmpty()) {
                        mission.setProcessOther(JSONUtil.toJsonStr(v.getCustomFieldVos()));
                    }
                    missionService.updateById(mission);
                } else {
                    mission = new Mission();
                    mission.setWorkOrderCode(wo.getCode());
                    mission.setProductCode(product.getCode());
                    mission.setProcessCode(pro.getCode());
                    if (v.getPlanedNumber() == null) {
                        mission.setPlanedNumber(vo.getPlanedNumber());
                    } else {
                        mission.setPlanedNumber(v.getPlanedNumber());
                    }
                    mission.setGoodProductNumber(BigDecimal.ZERO);
                    mission.setBadProductNumber(BigDecimal.ZERO);
                    mission.setProcessState(0);
                    if (v.getOrder() != null) {
                        mission.setLast(v.getOrder());
                    }
                    mission.setStartTime(Optional.ofNullable(v.getStartTime()).orElse(vo.getStartTime()));
                    mission.setEndTime(Optional.ofNullable(v.getEndTime()).orElse(vo.getEndTime()));
                    // 添加工序自定义字段
                    if (Objects.nonNull(v.getCustomFieldVos()) && !v.getCustomFieldVos().isEmpty()) {
                        mission.setProcessOther(JSONUtil.toJsonStr(v.getCustomFieldVos()));
                    }
                    BigDecimal rate = mission.getPlanedNumber().divide(wo.getPlanedNumber(), 6, RoundingMode.DOWN);
                    mission.setRate(rate);
                    missionService.save(mission);
                }
            }
            List<Integer> l = vo.getProcess().stream().map(MissionProcessVo::getId).collect(Collectors.toList());
            if (StringUtils.hasLength(vo.getProcessIds())) {
                wo.setProcessId(vo.getProcessIds());
            } else {
                wo.setProcessId(l.stream().map(String::valueOf).collect(Collectors.joining(",")));
            }
        }
        if (!CollectionUtils.isEmpty(vo.getCustomFieldVos()) || (Objects.nonNull(vo.getCustomFieldVos()) && vo.getCustomFieldVos().isEmpty())) {
            wo.setOther(customFieldService.handleObjectCreateOrEdit(vo.getCustomFieldVos()).toJSONString());
        } else if (!StringUtils.hasLength(wo.getCode())) {
            wo.setOther("");
        }
        workOrderService.updateById(wo);
        // 纠正erp库存
        if (sysFlag != 0) {
            PushOrderNumVo queryData = formTableService.getErpSalesInfo(wo.getCode());
            if (Objects.nonNull(queryData) && Objects.nonNull(queryData.getRemoteSaleId())) {
//                FormTableDetail formTableDetail = formTableDetailService.getOne(new LambdaQueryWrapper<FormTableDetail>().eq(FormTableDetail::getWorkOrderCode, wo.getCode()));
                queryData.setStatus(sysFlag).setFinishNum(wo.getActualNumber())/*.setSaleDetailId(formTableDetail.getId())*/;
                erpService.pushOrderNum(queryData);
            }
        }


        customEventService.sendCustomEventMsg(0, 0, 1, wo, null, null);
        cacheCustomToMongo(wo);
        if (Objects.nonNull(vo.getCustomFieldVos()) && vo.getCustomFieldVos().isEmpty()) {
            WorkOrder workOrder = new WorkOrder();
            workOrder.setCode(wo.getCode());
            workOrder.setId(wo.getId());
            mongoTemplate.save(workOrder);
        }
        return ResponseData.success("success");
    }

    public ResponseData workOrderCreate(Integer userId, WorkOrderHandleVo vo, HandleLog hl) {
        vo.setState(0);
        WorkOrder wo = BeanUtil.copyProperties(vo, WorkOrder.class).setCreateId(userId);
        if (StringUtil.isBlank(vo.getCode())) {
            String code = customNumberService.generator(4);
            if ("fail".equals(code)) {
                return ResponseData.fail(500, "流水号已用完，请手动输入");
            }
            wo.setCode(code);
        }
        WorkOrder wor = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", vo.getCode()));
        if (wor != null) {
            return ResponseData.fail(500, "已存在相同编号");
        }

        hl.setHandleDetail("创建工单成功，编号为【" + wo.getCode() + "】").setHandleCode(wo.getCode()).setHandleType("新增工单");
        handleLogService.save(hl);
        if (!CollectionUtils.isEmpty(vo.getProcess())) {
            Product product = productService.getById(wo.getProductId());
            List<String> processName = new ArrayList<>();
            for (MissionProcessVo v : vo.getProcess()) {
                Processes pro = processesService.getById(v.getId());
                Mission mission = new Mission();
                mission.setWorkOrderCode(wo.getCode());
                mission.setProductCode(product.getCode());
                mission.setProcessCode(pro.getCode());
                if (v.getPlanedNumber() == null) {
                    mission.setPlanedNumber(vo.getPlanedNumber());
                } else {
                    mission.setPlanedNumber(v.getPlanedNumber());
                }
                mission.setProcessName(pro.getName());
                mission.setGoodProductNumber(BigDecimal.valueOf(0));
                mission.setBadProductNumber(BigDecimal.valueOf(0));
                mission.setProcessState(0);
                mission.setIsUrgent(0);
                if (v.getOrder() != null) {
                    mission.setLast(v.getOrder());
                }
                if (v.getStartTime() != null) {
                    mission.setStartTime(v.getStartTime());
                } else {
                    mission.setStartTime(vo.getStartTime());
                }
                if (v.getEndTime() != null) {
                    mission.setEndTime(v.getEndTime());
                } else {
                    mission.setEndTime(vo.getEndTime());
                }
                BigDecimal rate = mission.getPlanedNumber().divide(wo.getPlanedNumber(), 6, BigDecimal.ROUND_DOWN);
                mission.setRate(rate);
                // 添加工序自定义字段
                if (Objects.nonNull(v.getCustomFieldVos()) && !v.getCustomFieldVos().isEmpty()) {
                    mission.setProcessOther(JSONUtil.toJsonStr(v.getCustomFieldVos()));
                }
                missionService.save(mission);
                missionService.cacheCustomToMongo(mission);
                processName.add(pro.getName());
                customEventService.sendCustomEventMsg(1, 0, 0, null, mission, null);
            }
            List<Integer> l = vo.getProcess().stream().map(MissionProcessVo::getId).collect(Collectors.toList());
            wo.setProcessId(l.stream().map(String::valueOf).collect(Collectors.joining(",")));
        }
        if (!CollectionUtils.isEmpty(vo.getCustomFieldVos())) {
            wo.setOther(customFieldService.handleObjectCreateOrEdit(vo.getCustomFieldVos()).toJSONString());
        }
        workOrderService.save(wo);

        // 设置工单二维码
        WorkOrder newWorkOrder = new WorkOrder().setId(wo.getId());
        String fileName = qRFilePrefix + System.currentTimeMillis() + ".jpg";
        QrCodeUtil.generate(String.format("workerOrderId=%d", wo.getId()), 300, 300, cn.hutool.core.io.FileUtil.file(fileName));
        newWorkOrder.setQr(fileName);
        newWorkOrder.setOther(wo.getOther());
        workOrderService.updateById(newWorkOrder);
        cacheCustomToMongo(wo);
        customEventService.sendCustomEventMsg(0, 0, 0, wo, null, null);
        return ResponseData.success("success", Collections.singletonMap("workOrderId", wo.getId()));
    }


    public ResponseData getDetail(IdVo vo) {
        WorkOrderDetailResp workOrderDetailResp = workOrderService.getBaseMapper().getWorkOrder(new QueryWrapper<WorkOrderDetailResp>().eq("wo.id", vo.getId()));
        List<WOMissionResp> list;
        if (workOrderDetailResp == null) {
            Mission mission = missionService.getById(vo.getId());
            WorkOrder order = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", mission.getWorkOrderCode()));
            workOrderDetailResp = workOrderService.getBaseMapper().getWorkOrder(new QueryWrapper<WorkOrderDetailResp>().eq("wo.id", order.getId()));
        }
        Integer loginUserId = LoginUtil.getLoginUserId();
        User currentUser = userService.getById(loginUserId);
        if (workOrderDetailResp != null) {
            list = missionService.getBaseMapper().getWODetailMission(new QueryWrapper<WOMissionResp>().eq("m.work_order_code", workOrderDetailResp.getWorkOrderCode()));
            if (!CollectionUtils.isEmpty(list)) {
                List<WOMissionResp> finalList = list;
                list.forEach(l -> {
                    if (StringUtil.isNotBlank(l.getPermission())) {

                        if (l.getPermissionsName().contains("所有人")) {
                            l.setPermissionsName("所有人");
                        } else {
                            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>().in(User::getId, Arrays.asList(l.getPermission().split(",")));
                            String permissionsName = userService.list(userLambdaQueryWrapper).stream().map(User::getName).collect(Collectors.joining(","));
                            l.setPermissionsName(permissionsName);
                        }
                        l.setDiffId(finalList.indexOf(l));
                    }
                    String badProductList = missionService.getBaseMapper().getBadProductListByMissionId(l.getMissionId(), LoginUtil.getLoginUserFactory());
                    l.setBadProductList(badProductList);
                    // 添加工单中工序自定义字段
                    if (StringUtils.hasLength(l.getProcessOther())) {
                        l.setCustomFieldVos(JSONUtil.parseArray(l.getProcessOther()).toList(CustomFieldVo.class));
                    }
                });
            }
            workOrderDetailResp.setMissionList(list);
        }
        if (Objects.nonNull(workOrderDetailResp) && StringUtil.isNotBlank(workOrderDetailResp.getOther())) {
            workOrderDetailResp.setCustomFieldVos(customFieldService.handleCustomFieldForList(workOrderDetailResp.getOther()));
        }
        // 生成二维码
        try {
            if (Objects.nonNull(workOrderDetailResp) && !StringUtils.hasLength(workOrderDetailResp.getQr())) {
                // 设置工单二维码
                WorkOrder workOrder = workOrderService.getById(workOrderDetailResp.getId());
                WorkOrder newWorkOrder = new WorkOrder().setId(workOrderDetailResp.getId());
                String fileName = qRFilePrefix + System.currentTimeMillis() + ".jpg";
                QrCodeUtil.generate(String.format("workerOrderId=%d", workOrderDetailResp.getId()), 300, 300, cn.hutool.core.io.FileUtil.file(fileName));
                newWorkOrder.setQr(fileName);
                workOrderDetailResp.setQr(fileName);
                newWorkOrder.setActualStartTime(workOrder.getActualStartTime());
                newWorkOrder.setActualEndTime(workOrder.getActualEndTime());
                newWorkOrder.setOther(workOrderDetailResp.getOther());
                workOrderService.updateById(newWorkOrder);
            }
        } catch (Exception e) {
            log.error("生成二维码错误,工单id:{}", workOrderDetailResp.getId());
        }
        if (Objects.nonNull(workOrderDetailResp) && StringUtils.hasLength(workOrderDetailResp.getQr())) {
            workOrderDetailResp.setQr(workOrderDetailResp.getQr().replace("/service", ""));
        }
        return ResponseData.success(workOrderDetailResp);
    }

    public void handleImport(MultipartFile file, Integer type) throws IOException {

        // 当前时间
        Date date = new Date();
        DateTime beginOfDay = DateUtil.beginOfDay(date);
        DateTime endOfDay = DateUtil.offsetSecond(DateUtil.endOfDay(date), -1);


        byte[] stream = IoUtils.toByteArray(file.getInputStream());
        List<Map<String, String>> allDataList = EasyExcelImportUtils.parseExcelToData(stream, 2, "工单编号");

        // 空值导入日志
        userService.importBlankExcel(allDataList, "workOrder");

        List<ColumnsConfigureList> allList = userService.handleDefault();
        Map<String, Integer> dataMap = new HashMap<>();
        List<Map<String, String>> failList = new ArrayList<>();
        int a = 0;
        int b = 0;
        if (allList.stream().filter(f -> f.getType().equals("workOrder")).findAny().orElse(null) != null) {
            List<ColumnsConfigure> list = allList.stream().filter(f -> f.getType().equals("workOrder")).findAny().orElse(null).getColumns();
            String depS = "";
            for (Map<String, String> s : allDataList) {
                Map<String, String> failMap = new HashMap<>();
                failMap.put("产品名称", "-");
                failMap.put("规格描述", "-");
                WorkOrder wo = new WorkOrder();
                Product product = new Product();
                List<CustomFieldVo> vos = new ArrayList<>();
                //表头
                List<String> keyList = new ArrayList<>(s.keySet());
                int flag = 0;
                for (int i = 0; i < keyList.size() && flag == 0; i++) {
                    if (i >= list.size()) {
                        CustomField cf = customFieldService.getOne(new QueryWrapper<CustomField>().eq("field_ascription", "workOrder").eq("chinese_name", keyList.get(i)));
                        CustomFieldVo vo = new CustomFieldVo();
                        vo.setCustomFieldId(cf.getId());
                        vo.setValue(s.get(keyList.get(i)));
                        vos.add(vo);
                    } else {
                        switch (i) {
                            case 0:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    WorkOrder woOld = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", s.get(keyList.get(i))));
                                    if (woOld != null && type == 1) {
                                        if (woOld.getState() == 1) {
                                            failMap.put("失败原因", "工单状态执行中不可覆盖");
                                            failMap.put("工单编号", s.get(keyList.get(i)));
                                            failMap.put("计划数", "-");
                                            failList.add(failMap);
                                            b++;
                                            flag = 1;
                                            break;
                                        }
                                        wo = woOld;
                                    } else if (woOld != null) {
                                        failMap.put("失败原因", "系统内已存在相同编号工单");
                                        failMap.put("工单编号", s.get(keyList.get(i)));
                                        failMap.put("计划数", "-");
                                        failList.add(failMap);
                                        b++;
                                        flag = 1;
                                        break;
                                    } else {
                                        wo.setCode(s.get(keyList.get(i)));
                                    }
                                } else {
                                    String code = customNumberService.generator(4);
                                    if (code.equals("fail")) {
                                        failMap.put("失败原因", "流水号已用完，请手动输入");
                                        failMap.put("工单编号", "-");
                                        failMap.put("计划数", "-");
                                        failList.add(failMap);
                                        b++;
                                        flag = 1;
                                        break;
                                    }
                                    wo.setCode(code);
                                }
                                continue;
                            case 1:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    product = productService.getOne(new QueryWrapper<Product>().eq("code", s.get(keyList.get(i))));
                                    if (product == null) {
                                        failMap.put("失败原因", "产品不存在");
                                        failMap.put("工单编号", "-");
                                        failMap.put("计划数", Optional.ofNullable(s.get(keyList.get(2))).orElse("0"));
                                        failList.add(failMap);
                                        b++;
                                        flag = 1;
                                        break;
                                    } else {
                                        failMap.put("产品名称", product.getName());
                                        failMap.put("规格描述", product.getSpecification());
                                        wo.setProductId(product.getId());
                                    }
                                }
                                continue;
                            case 2:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    wo.setPlanedNumber(BigDecimal.valueOf(Double.parseDouble(s.get(keyList.get(i)))));
                                }
                                continue;
                            case 3:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    List<Processes> listProcesses = processesService.list(new QueryWrapper<Processes>().in("name", Arrays.asList(s.get(keyList.get(i)).split(","))));
                                    if (!CollectionUtils.isEmpty(listProcesses)) {
                                        if (type != 1) {
                                            wo.setProcessId(listProcesses.stream().map(m -> m.getId()).map(m -> m + "").collect(Collectors.joining(",")));
                                        } else {
//                                            wo.setProcessId(wo.getProcessId()+","+listProcesses.stream().map(m -> m.getId()).map(m -> m + "").collect(Collectors.joining(",")));
                                            // 暂定为替换并删除任务
                                            missionService.remove(new LambdaQueryWrapper<Mission>().eq(Mission::getWorkOrderCode, wo.getCode()));
                                            wo.setProcessId(listProcesses.stream().map(m -> m.getId().toString()).collect(Collectors.joining(",")));
                                        }
                                        Product finalProduct = product;
                                        WorkOrder finalWo = wo;
                                        listProcesses.forEach(f -> {
                                            Mission m = new Mission();
                                            m.setRate(BigDecimal.ONE);
                                            m.setWorkOrderCode(finalWo.getCode());
                                            m.setProcessCode(f.getCode());
                                            m.setProductCode(finalProduct.getCode());
                                            m.setPlanedNumber(finalWo.getPlanedNumber());
                                            m.setProcessState(0);
                                            m.setIsUrgent(0);
                                            if (listProcesses.indexOf(f) == listProcesses.size() - 1) {
                                                m.setLast(0);
                                            } else {
                                                m.setLast(listProcesses.indexOf(f) + 1);
                                            }
                                            m.setStartTime(beginOfDay);
                                            m.setEndTime(endOfDay);
                                            missionService.save(m);
                                        });
                                    } else {
                                        failMap.put("失败原因", "工序不存在");
                                        failMap.put("工单编号", "-");
                                        failMap.put("计划数", Optional.ofNullable(s.get(keyList.get(2))).orElse("-"));
                                        failList.add(failMap);
                                        b++;
                                        flag = 1;
                                        break;
                                    }
                                } else {
                                    failMap.put("失败原因", "工序不存在");
                                    failMap.put("工单编号", "-");
                                    failMap.put("计划数", Optional.ofNullable(s.get(keyList.get(2))).orElse("-"));
                                    failList.add(failMap);
                                    b++;
                                    flag = 1;
                                    break;
                                }
                                continue;
                            case 4:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    wo.setStartTime(TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, s.get(keyList.get(i))) == null ?
                                            TimeUtil.parseDate("yyyy-MM-dd HH:mm", s.get(keyList.get(i))) : TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, s.get(keyList.get(i))));
                                } else {
                                    wo.setStartTime(beginOfDay);
                                }
                                continue;
                            case 5:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    wo.setEndTime(TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, s.get(keyList.get(i))) == null ?
                                            TimeUtil.parseDate("yyyy-MM-dd HH:mm", s.get(keyList.get(i))) : TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, s.get(keyList.get(i))));
                                } else {
                                    wo.setEndTime(endOfDay);
                                }
                                continue;
                            case 6:
                                if (StringUtil.isNotBlank(s.get(keyList.get(i)))) {
                                    wo.setComment(s.get(keyList.get(i)));
                                }
                                continue;
                        }
                    }
                }
                if (flag == 0) {


                    if (!CollectionUtils.isEmpty(vos)) {
                        List<CustomFieldVo> existCustom = vos.stream().filter(i -> Objects.nonNull(i.getValue())).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(existCustom)) {
                            wo.setOther(customFieldService.handleObjectCreateOrEdit(existCustom).toJSONString());
                        }

                    }
                    wo.setCreateId(LoginUtil.getLoginUserId());
                    wo.setEditId(LoginUtil.getLoginUserId());
                    wo.setCreateTime(new Date());
                    wo.setIsUrgent(0);
                    boolean result = workOrderService.saveOrUpdate(wo);
                    if (result) {
                        a++;
                        cacheCustomToMongo(wo);
                    }
                }
            }
            userService.importLog(LoginUtil.getLoginAccount(), allDataList.size(), OwnUtil.getImportLogDataMap(dataMap, a, b, type), "workOrder", failList);
        }

    }


    public List<WorkOrderResp> getEventSearchResult(WorkOrderListVo vo) {
        IPage<WorkOrderResp> data = workOrderService.getBaseMapper().selectForList(new Page<WorkOrderResp>(0, 10000), vo.getCode(), vo.getProductCode(),
                vo.getProductName(), vo.getProductSpecification(), vo.getUnit(), vo.getComment(), vo.getPlanedNumberDown(), vo.getPlanedNumberUp(), vo.getActualNumberDown(),
                vo.getActualNumberUp(), vo.getGoodProductNumberDown(), vo.getGoodProductNumberUp(), vo.getBadProductNumberDown(), vo.getBadProductNumberUp(),
                vo.getStartTimeStart(), vo.getStartTimeEnd(), vo.getEndTimeStart(), vo.getEndTimeEnd(), vo.getActualStartTimeStart(), vo.getActualStartTimeEnd(),
                vo.getActualEndTimeStart(), vo.getActualEndTimeEnd(), vo.getState(), null, null);
        List<WorkOrderResp> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            if (vo.getCustomFieldMap() != null) {
                data.getRecords().forEach(d -> {
                    if (StringUtil.isNotBlank(d.getOther())) {
                        Map<Integer, String> dataMap = JSONArray.parseArray(d.getOther()).toJavaList(CustomFieldVo.class)
                                .stream().collect(Collectors.toMap(CustomFieldVo::getCustomFieldId, CustomFieldVo::getValue));
                        AtomicBoolean re = new AtomicBoolean(false);
                        vo.getCustomFieldMap().keySet().forEach(f -> {
                            CustomField cf = customFieldService.getById(Integer.valueOf(String.valueOf(f)));
                            String value = vo.getCustomFieldMap().get(f);
                            if (cf.getFieldType().equals("datePicker")) {
                                if (dataMap.get(f) != null && StringUtil.isNotBlank(dataMap.get(f))) {
                                    Date dataTime = TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, dataMap.get(f));
                                    Date start = TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, value.split(",")[0]);
                                    Date end = TimeUtil.parseDate(TimeUtil.DEFAULT_DATE_FORMAT, value.split(",")[1]);
                                    re.set(TimeUtil.isEffectiveDate(dataTime, start, end));
                                }
                            } else if (cf.getFieldType().equals("inputNumber")) {
                                if (dataMap.get(f) != null && StringUtil.isNotBlank(dataMap.get(f))) {
                                    Integer dataNum = Integer.valueOf(dataMap.get(f));
                                    Integer start = Integer.valueOf(vo.getCustomFieldMap().get(f));
                                    Integer end = Integer.valueOf(vo.getCustomFieldMap().get(f));
                                    re.set(dataNum > start && dataNum < end);
                                }
                            } else if (StringUtil.isNotBlank(dataMap.get(f)) && dataMap.get(f).equals(vo.getCustomFieldMap().get(f))) {
                                re.set(true);
                            }
                        });
                        if (re.get()) {
                            result.add(d);
                        }
                    }
                });
            } else {
                result.addAll(data.getRecords());
            }
        }
        return result;
    }

    /**
     * 根据id获取导出数据
     *
     * @param id 工单id
     */
    public Map<String, Object> getExportData(Integer id) {
        return this.baseMapper.getExportData(id);
    }

    /**
     * 根据id获取任务相关信息
     *
     * @param id 工单id
     */
    public List<Map<String, Object>> getExportProcessList(Integer id) {
        return this.baseMapper.getExportProcessList(id);
    }

    /**
     * 计算工时
     *
     * @param workOrderCode 工单编码
     */
    public Long completeWorkReport(String workOrderCode) {
        return this.baseMapper.completeWorkReport(workOrderCode);
    }

    /**
     * 获取按类型分类数据
     *
     * @param searchCondition 查询条件
     * @return 分类数量数据
     */
    public List<GroupCountVo> getTypeCountMap(WorkListMergedConditionVo searchCondition, String groupColumn) {
        Map<String, String> typeValueNameMap = new HashMap<>(10);
        List<String> typeChineseName = new ArrayList<>(1);
        switch (groupColumn) {
            case "state":
                typeChineseName.add(0, "工单状态");
                typeValueNameMap.put("0", "未开始");
                typeValueNameMap.put("1", "执行中");
                typeValueNameMap.put("2", "已结束");
                typeValueNameMap.put("3", "已取消");
                searchCondition.setState(null);
                break;
        }
        List<GroupCountVo> typeCountData = this.baseMapper.getTypeCountMap(searchCondition, groupColumn);
        typeCountData.forEach(i -> {
            i.setTypeName(typeChineseName.get(0)).setOptionName(typeValueNameMap.get(i.getOptionValue()));
            typeValueNameMap.remove(i.getOptionValue());
        });
        typeValueNameMap.forEach((k, v) -> {
            typeCountData.add(new GroupCountVo().setOptionNum(0L).setTypeName(typeChineseName.get(0)).setOptionName(v).setOptionValue(k));
        });

        return typeCountData.stream().sorted(Comparator.comparingInt(f -> Integer.parseInt(f.getOptionValue()))).collect(Collectors.toList());
    }

    /**
     * 获取工单概览
     *
     * @param param 工单概览查询条件
     * @return 分类数量数据
     */
    public Page<WorkOrderResp> getWorkOrderOverview(WorkOrderOverviewQuery param) {
        Page<WorkOrderResp> workOrderOverview = this.baseMapper.getWorkOrderOverview(new Page<>(param.getPage(), param.getLimit()), param);
        if (!CollectionUtils.isEmpty(workOrderOverview.getRecords())) {
            List<WorkOrderResp> records = workOrderOverview.getRecords();
            Set<String> workOrderCodes = records.stream().map(WorkOrderResp::getCode).collect(Collectors.toSet());
            Map<String, List<ProcessStatisticsVo>> workOrderCodesProcessMap = processesService.getBaseMapper().getByOrderCodes(workOrderCodes).stream().collect(Collectors.groupingBy(ProcessStatisticsVo::getWorkOrderCode));
            records.forEach(i -> {
                i.setIsDelay(Objects.nonNull(i.getEndTime()) && DateTime.now().isBefore(i.getEndTime()) ? 0 : 1);
                List<WOProcessListResp> processData = workOrderCodesProcessMap.getOrDefault(i.getCode(), Collections.emptyList()).stream()
                        .sorted((f, s) -> ((f.getLast() == 0 || s.getLast() == 0) && !f.getLast().equals(s.getLast())) ? (f.getLast() == 0 ? 1 : -1) : (f.getLast() - s.getLast()))
                        .map(j -> {
                            WOProcessListResp woProcessListResp = new WOProcessListResp().setMissionId(j.getMissionId()).setProcessCode(j.getProcessCode()).setProcessName(j.getProcessName()).setProcessState(j.getProcessStatus())
                                    .setGoodProductNumber(j.getGoodNum()).setPlanedNumber(j.getPlanNum());
                            woProcessListResp.setRate(Objects.isNull(j.getPlanNum()) || j.getPlanNum().compareTo(BigDecimal.ZERO) == 0 ? j.getPlanNum() : (j.getGoodNum().divide(j.getPlanNum(), 4, RoundingMode.HALF_UP)));
                            return woProcessListResp;
                        })
                        .collect(Collectors.toList());
                i.setList(processData);
            });
        }
        return workOrderOverview;
    }


    /**
     * 缓存工单自定义字段
     */
    public void cacheCustomToMongo(WorkOrder wo) {
        if (StringUtils.hasLength(wo.getOther())) {
            JSONArray objects = JSONArray.parseArray(wo.getOther());
            if (!CollectionUtils.isEmpty(objects)) {
                WorkOrder workOrder = new WorkOrder();
                workOrder.setId(wo.getId());
                workOrder.setCode(wo.getCode());
                workOrder.setCustomFieldMess(JSONArray.parseArray(wo.getOther()));
                mongoTemplate.save(workOrder);
            }

        }
    }

    /**
     * 更新状态
     *
     * @return 错误信息  正确为null
     */
    public String changeStatus(WorkOrder newOrder, WorkOrder oriWorkOrder, List<Mission> updateMissions) {
        if (Objects.nonNull(newOrder.getState()) && !newOrder.getState().equals(oriWorkOrder.getState())) {
            Integer oriState = oriWorkOrder.getState();
            switch (newOrder.getState()) {
                case 0:
                    if (oriState != 1) {
                        return "工单非执行中状态不能回退至未开始";
                    }
                    newOrder.setActualStartTime(null);
                    break;
                case 1:
                    if (oriState == 0) {
                        newOrder.setActualStartTime(new Date());
                    }
                    if (oriState == 2) {
                        newOrder.setActualEndTime(null);
                    }
                    break;
                case 2:
                    if (oriState != 0 && oriState != 1) {
                        return "工单状态非未开始、执行中，不可结束";
                    }
                    //未开始直接结束给实际开始时间??
//                    newOrder.setActualStartTime(Optional.ofNullable(oriWorkOrder.getActualStartTime()).orElse(new Date()));
                    newOrder.setActualEndTime(new Date());
                    break;
            }
            if ((newOrder.getState() != 1 && newOrder.getState() != 3) || (newOrder.getState() == 1 && oriState == 2)) {
                String errMission = null;
                for (Mission i : updateMissions) {
                    Mission oriMission = BeanUtil.copyProperties(i, Mission.class);
                    i.setProcessState(newOrder.getState());
                    errMission = missionService.changeStatus(i, oriMission);
                    if (Objects.nonNull(errMission)) {
                        break;
                    }
                }
                if (Objects.nonNull(errMission)) {
                    return errMission;
                }
            }
        }
        return null;
    }

    //根据工单编码删除工单，任务及报工
    public void removeByCodeList(Set<String> wOCodes) {
        // 获取任务ids
        if (!wOCodes.isEmpty()) {
            List<Mission> missionList = missionService.list(new LambdaQueryWrapper<Mission>().in(Mission::getWorkOrderCode, wOCodes));
            if (!CollectionUtils.isEmpty(missionList)) {
                List<Integer> missionIds = missionList.stream().map(Mission::getId).collect(Collectors.toList());
                productService.rectifyStockByDelMissionIds(missionIds);
                // 删除报工
                workReportService.remove(new LambdaQueryWrapper<WorkReport>().in(WorkReport::getMissionId, missionIds));
                // 删除任务
                missionService.removeByIds(missionIds);
            }

            // 删除工单
            workOrderService.remove(new LambdaQueryWrapper<WorkOrder>().in(WorkOrder::getCode, wOCodes));
        }
    }

    /**
     * h5获取工单列表
     */
    public IPage<WorkOrderResp> h5GetWorkOrder(Page<WorkOrder> page, WorkListMergedConditionVo searchCondition) {
        IPage<WorkOrderResp> data = this.baseMapper.h5GetWorkOrder(page, searchCondition);
        ColumnUtils columnUtils = new ColumnUtils(customFieldService, ObjectType.workOrder.getCode());
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                if (StringUtil.isNotBlank(d.getProcessId())) {
                    List<String> processIds = Arrays.asList(d.getProcessId().split(","));
                    //返回任务里的工序名称（包含工序名称，计划数，工序状态）
                    List<WOProcessListResp> list = processesService.getBaseMapper().getWorkOrderProcessByIds(processIds, d.getCode());
                    d.setList(list);
                }
                d.setIsDelay(0);
                if (d.getState() != 2 && d.getState() != 3 && !TimeUtil.afterNow(d.getEndTime())) {
                    d.setIsDelay(1);
                }
                d.setCustomFieldVos(columnUtils.getCuColumnsByJsonArray(d.getOther()));
            });
        }
        return data;
    }

    //获取符合条件的工单数量
    public long getGroupCountVo(WorkListMergedConditionVo query) {
        return this.baseMapper.getGroupCountVo(query);
    }


    /**
     * 获取二级分组数量统计
     *
     * @param screenPlanId    筛选方案id,
     * @param searchCondition 查询条件
     * @return 类型数量统计
     */
    public List<GroupCountVo> getSecondGroupTypeCount(Integer screenPlanId, WorkListMergedConditionVo searchCondition) {
        // 获取看板二级分组按类型获取数据条数
        if (Objects.nonNull(screenPlanId)) {
            List<GroupCountVo> typeCountData = new ArrayList<>();
            ScreenPlan screenPlan = screenPlanService.getById(screenPlanId);
            String secondGroup = screenPlan.getSecondGroup();
            if ("工单状态".equals(secondGroup)) {
                secondGroup = "状态";
            }
            Map<String, String> cnEnMap = ColumnUtils.BASE_COLUMN_CN_EN_MAP.getOrDefault(ObjectType.workOrder.getCode(), Collections.emptyMap());
            String enName = cnEnMap.get(secondGroup);
            if (Objects.nonNull(enName)) {
                searchCondition.setSecondGroupColumnName(enName);
                typeCountData.addAll(workOrderService.getTypeCountMap(searchCondition, enName));
            } else {
                CustomField customField = customFieldService.getById(secondGroup);
                searchCondition.setSecondGroupColumnName(secondGroup);
                if (Objects.nonNull(customFieldService.getById(secondGroup))) {
                    List<RadioOptionVo> options = JSONUtil.toList(Optional.ofNullable(customField.getCheckBox()).orElse("[]"), RadioOptionVo.class);
                    options.forEach(i -> {
                        List<Integer> ids = customFieldService.searchCustomField(Collections.singletonMap(customField.getId(), i.getValue()), "workOrder");
                        searchCondition.setIds(ids);
                        long total = workOrderService.getGroupCountVo(searchCondition);
                        typeCountData.add(new GroupCountVo().setOptionNum(total).setOptionName(i.getValue()).setOptionValue(i.getValue()).setTypeName(customField.getChineseName()));
                    });
                }
            }
            return typeCountData;
        }
        return Collections.emptyList();
    }

    public IPage<WorkOrderResp> getList(Page<WorkOrder> page, WorkListMergedConditionVo searchCondition, String sortInfoStr) {
        IPage<WorkOrderResp> data = this.baseMapper.getList(page, searchCondition, sortInfoStr);
        ColumnUtils columnUtils = new ColumnUtils(customFieldService, ObjectType.workOrder.getCode());
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            Set<String> workOrderCodes = data.getRecords().stream().map(WorkOrderResp::getCode).collect(Collectors.toSet());
            Map<String, RelatedSalesInfoVo> codeDataMap = new HashMap<>();
            formTableService.getSalesInfoByWorkOrderCodes(workOrderCodes).forEach(i -> {
                Arrays.stream(i.getWorkOrderCode().split(",")).forEach(d->codeDataMap.put(d,i));
            });
            data.getRecords().forEach(d -> {
                if (StringUtil.isNotBlank(d.getProcessId())) {
                    List<String> processIds = Arrays.asList(d.getProcessId().split(","));
                    //返回任务里的工序名称（包含工序名称，计划数，工序状态）
                    List<WOProcessListResp> list = processesService.getBaseMapper().getWorkOrderProcessByIds(processIds, d.getCode());
                    d.setList(list);
                }
                d.setIsDelay(0);
                if (d.getState() != 2 && d.getState() != 3 && !TimeUtil.afterNow(d.getEndTime())) {
                    d.setIsDelay(1);
                }
                d.setCustomFieldVos(columnUtils.getCuColumnsByJsonArray(d.getOther()));
                if (!codeDataMap.isEmpty()) {
                    d.setRelatedSalesInfoVo(codeDataMap.get(d.getCode()));
                }
                if (StringUtils.hasLength(d.getQr())) {
                    d.setQr(d.getQr().replace("/service", ""));
                }
            });
        }
        return data;
    }


}

